home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / gfx / show / MerlinGfx.lha / read.c < prev    next >
C/C++ Source or Header  |  1995-06-07  |  16KB  |  654 lines

  1. /*    MerlinFLI - Rainer Trunz, Januar 1995
  2.  
  3.     This file, read.c, was taken over from the original xflick
  4.     source with a lot(!) of modifications - see comments and
  5.     code, the include file change below, and a call to the
  6.     new error/exit routine 'Quit' instead of 'xferror'.
  7.  
  8.     Here is the original comment:
  9.  
  10.          xflick - Ron Schnell, March, 1991
  11.  
  12.      This code is provided as is, with no warrantees, expressed
  13.          or implied.  I believe this code to be free of encumbrance,
  14.      and offer it to the public domain.  I ask, however, that
  15.      this paragraph and my name be retained in any modified
  16.      versions of the file you may make, and that you notify me
  17.      of any improvements you make to the code.
  18.  
  19.      Ron Schnell (ronnie@sos.com)
  20.  
  21.     The following changes are from Michael Pall
  22.     (pall@rz.uni-karlsruhe.de) Mar 25-28 1991:
  23.  
  24.     Lots of bugfixes and changes to the structure of the files.
  25.     The interpretation part is now in this file.
  26.  
  27.     This is read.c, the functions which read in
  28.     FLI structures in a machine independent format.
  29. */
  30.  
  31. #include <proto/dos.h>
  32.  
  33. #include "eflick.h"
  34. #include "proto.h"
  35.  
  36. #include <sys/types.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39.  
  40. enum {
  41.     NO_ERR = 1,
  42.     MEM_ERR,
  43.     GFX_ERR,
  44.     INT_ERR,
  45.     SYS_ERR,
  46.     REN_ERR,
  47.     DBL_ERR,
  48.     SCR_ERR,
  49.     REQ_ERR,
  50.     WIN_ERR,
  51.     FND_ERR,
  52.     PIP_ERR,
  53.     DRI_ERR,
  54.     PAR_ERR,
  55.     MPG_ERR,
  56.     RNG_ERR,
  57.     GET_ERR,
  58.     BRK_ERR,
  59.     GAD_ERR,
  60.     VIS_ERR,
  61.     MEN_ERR
  62. };
  63.  
  64. #ifndef TRUE
  65. #define TRUE 1
  66. #define FALSE 0
  67. #endif
  68.  
  69. #define grab_short(p)\
  70.   ({int i=*((unsigned char *)p++); i |= *((unsigned char *)p++) << 8; i;})
  71.  
  72. #define get_short(p) (grab_short(p) & 0x0000ffff)
  73.  
  74. #define get_long(p) grab_short(p) + (grab_short(p) << 16)
  75.  
  76. /* #define DEBUGGING 1 */
  77.  
  78. extern int verbose;
  79. extern void Quit(int);
  80.  
  81. /*****************************************************************************
  82.  *
  83.  * get_short - PeeCee-Schrott für baserel Gnu-C ;-(((
  84.  *
  85.  * ©`95 Rainer F. Trunz. Geschrieben für Gnu-C 2.3.3 !
  86.  *
  87.  * strange,strange,strange.. funktioniert mal, mal nicht #!?
  88.  *****************************************************************************/
  89. /*
  90. #define get_short(x)    \
  91.   ({int res; unsigned char *arg = (x);    \
  92.     __asm __volatile ("            \
  93.     moveq    #0,d0; movel %1,a0;    \
  94.     moveb    a0@+,d0;        \
  95.     moveb    a0@+,d1;        \
  96.     lslw    #8,d1;orw d1,d0;    \
  97.     movel    a0,%1;            \
  98.     movel    d0,%0"            \
  99.     : "=f" (res)    * Output *    \
  100.     : "r"  (arg)    * Input *    \
  101.     : "d0", "d1", "a0"); res;})
  102.  
  103. #define get_long(x)    \
  104.   ({int res; unsigned char *arg = (x);    \
  105.     __asm __volatile ("        \
  106.     moveq    #0,d0; movel %1,a0;    \
  107.     moveb    a0@+,d0;        \
  108.     moveb    a0@+,d1;        \
  109.     lslw    #8,d1;orw d1,d0;swap d0;\
  110.     moveb    a0@+,d0;        \
  111.     moveb    a0@+,d1;        \
  112.     lslw    #8,d1;orw d1,d0;swap d0;\
  113.     movel    a0,%1;            \
  114.     movel    d0,%0"            \
  115.     : "=f" (res)    * Output *    \
  116.     : "r" (arg)    * Input *    \
  117.     : "d0", "d1", "a0"); res;})
  118. */
  119.  
  120. void
  121. read_flihead (BPTR fd, struct fli_header *header)
  122. {
  123.     unsigned char *buf, *sbf;
  124.     int i;
  125.  
  126.     if (!(buf = (unsigned char *)malloc(SIZE_HEADER)))
  127.       Quit (MEM_ERR);
  128.  
  129.     sbf = buf;
  130.  
  131.     if (FRead (fd, buf, SIZE_HEADER, 1) < 1)
  132.       Quit (GET_ERR);
  133.  
  134.     header->fhd_size = get_long(buf);
  135.  
  136.     header->fhd_magic = get_short(buf);
  137.  
  138.     header->fhd_frames = get_short(buf);
  139.  
  140.     header->fhd_width = get_short(buf);
  141.  
  142.     header->fhd_height = get_short(buf);
  143.  
  144.     header->fhd_gap = get_short(buf);
  145.  
  146.     header->fhd_flags = get_short(buf);
  147.  
  148.     header->fhd_speed = get_short(buf);
  149.  
  150.     header->fhd_next = get_long(buf);
  151.  
  152.     header->fhd_frit = get_long(buf);
  153.  
  154.     memcpy (buf, header->fhd_expand, FHD_EXPAND_SIZE);
  155.  
  156.     free (sbf);
  157.  
  158.     /* Seek (fd, SIZE_HEADER, OFFSET_BEGINNING); */
  159.  
  160.     if (verbose) {
  161.       Printf ("header->fhd_size:   %ld\n", header->fhd_size);
  162.       Printf ("header->fhd_magic:  0x%lx\n", header->fhd_magic);
  163.       Printf ("header->fhd_frames: %ld\n", header->fhd_frames);
  164.       Printf ("header->fhd_width:  %ld\n", header->fhd_width);
  165.       Printf ("header->fhd_height: %ld\n", header->fhd_height);
  166.       Printf ("header->fhd_gap:    0x%lx\n", header->fhd_gap);
  167.       Printf ("header->fhd_flags:  0x%lx\n", header->fhd_flags);
  168.       Printf ("header->fhd_speed:  %ld\n", header->fhd_speed);
  169.       Printf ("header->fhd_next:   %ld\n", header->fhd_next);
  170.       Printf ("header->fhd_frit:   0x%lx\n", header->fhd_frit);
  171.       Printf ("header->fhd_expand: ");
  172.  
  173.       for (i = 0; i < FHD_EXPAND_SIZE; i++)
  174.     Printf ("%lx ", 0xff & (unsigned int)header->fhd_expand[i]);
  175.       Printf ("\n");
  176.     }
  177. }
  178.  
  179. void
  180. read_fheader (BPTR fd, struct frame_header *fheader)
  181. {
  182.     unsigned char data[SIZE_FHEADER];
  183.     unsigned char *buf = data;
  184.     int syncNotFound = TRUE;
  185.     int ret, i;
  186.  
  187.     i = 0;    /* Syncronize to the magic word */
  188.  
  189.     do {
  190.       ret = FGetC (fd);
  191.       ++i;
  192.  
  193.       if (verbose)
  194.     Printf ("Read1 i: %ld Byte: 0x%lx sync: %s\n",
  195.         i, 0xff & (unsigned int)ret, syncNotFound?"TRUE":"FALSE");
  196.  
  197.       if (ret == (unsigned char)0xfa) {
  198.     ret = FGetC (fd);
  199.     ++i;
  200.  
  201.     if (ret == (unsigned char)0xf1)
  202.       syncNotFound = FALSE;
  203.     else
  204.       syncNotFound = TRUE;
  205.  
  206.     if (verbose)
  207.       Printf ("Read2 i: %ld Byte: 0x%lx sync: %ld\n",
  208.           i, 0xff & (unsigned int)ret, syncNotFound);
  209.       }
  210.     } while ((syncNotFound == TRUE) && (ret >= 0));
  211.  
  212.     if (ret < 0) {
  213.       Printf ("Error reading input file looking for"
  214.             " frame header magic number. i: %ld\n", i);
  215.       Quit (GET_ERR);
  216.     }
  217.     if (verbose)
  218.       Printf ("After Sync i: %ld sync: %s ret: %ld\n",
  219.         i, syncNotFound?"TRUE":"FALSE", ret);
  220.  
  221.     if ((ret = Seek (fd, -6, OFFSET_CURRENT)) < 0) {
  222.       Printf ("Seeking to begining of frame\n");
  223.       Quit (GET_ERR);
  224.     }
  225.     if (FRead (fd, buf, SIZE_FHEADER, 1) < 1)
  226.       Quit (GET_ERR);
  227.  
  228.     fheader->fr_size = get_long(buf);
  229.     fheader->fr_magic = get_short(buf);
  230.     fheader->fr_chunks = get_short(buf);
  231.  
  232.     memcpy (buf, fheader->fr_expand, FR_EXPAND_SIZE);
  233.  
  234.     if (verbose) {
  235.       Printf ("fheader->fr_size:   %ld\n", fheader->fr_size);
  236.       Printf ("fheader->fr_magic:  0x%lx\n", fheader->fr_magic);
  237.       Printf ("fheader->fr_chunks: %ld\n", fheader->fr_chunks);
  238.       Printf ("fheader->fr_expand: ");
  239.  
  240.       for (i = 0; i < FR_EXPAND_SIZE; i++)
  241.      Printf ("%ld ", 0xff & (unsigned int)fheader->fr_expand[i]);
  242.  
  243.       Printf ("\n");
  244.     }
  245. }
  246.  
  247. static void inline
  248. read_chunk (BPTR fd, struct chunk_header *chunk)
  249. {
  250.     unsigned char data[SIZE_CHEADER];
  251.     unsigned char *buf = data;
  252.  
  253.     if (FRead (fd, buf, SIZE_CHEADER, 1) < 1)
  254.       Quit (GET_ERR);
  255.  
  256.     chunk->ch_bytes = get_long(buf);
  257.     chunk->ch_type = get_short(buf);
  258.  
  259.     if (verbose) {
  260.       Printf ("chunk->ch_bytes: %ld\n", chunk->ch_bytes);
  261.       Printf ("chunk->ch_type:  %ld\n", chunk->ch_type);
  262.     }
  263. }
  264.  
  265. void
  266. interpret_fli  (BPTR fd,            /* The file descriptor */
  267.         struct fli_header *header,    /* The header of the file */
  268.         unsigned char *data,        /* A pointer to the pixel data */
  269.         int notfirst,            /* Is this not the first time through? */
  270.         void (*func)() )        /* The function that stores or displays the chunks */
  271. {
  272.     int i, j, s, l, k;            /* Random look/status ints */
  273.     int ndiff;                /* To hold the # lines changed from last frame */
  274.     struct frame_header fheader;    /* To hold each frame header */
  275.     struct chunk_header chunk;        /* To hold each chunk header */
  276.     unsigned char *buf = NULL;        /* malloc'd space to hold each chunk */
  277.     int bufalloc;            /* Space already allocated for buf */
  278.     int skchange, skcount, sicount;    /* Various pixel/data index's */
  279.     unsigned char *cptr,*dptr,*eptr;    /* data pointers into *buf */
  280.     int npack;                /* Number of packets in this chunk */
  281.     unsigned char by, by0, by1;        /* To hold a byte */
  282.     int curx, cury;            /* The current x & y coords */
  283.     int wwidth, wheight;        /* Width and height of the window */
  284.     int topy,bottomy,leftx,rightx;    /* For optimizing FLI_LC chunks */
  285.  
  286.     static long twopos;            /* To keep the file offset of frame # 2 */
  287.  
  288.     wwidth = header->fhd_width;
  289.     wheight = header->fhd_height;
  290.  
  291.     for (i=0; i <= header->fhd_frames; i++)
  292.     {
  293.     /* if (SetSignal(0,0) & SIGBREAKF_CTRL_C)
  294.        Quit (NO_ERR); */
  295.  
  296.     /* The following stuff ist only needed if we display the frames
  297.        while we interpret the file */
  298.  
  299.     if ((notfirst) && (i==0))    /* If this is the first time through, */
  300.     {                /* we display frame # 1, */
  301.       Seek (fd, twopos, OFFSET_BEGINNING);
  302.       continue;            /* otherwise, we skip right to frame two */
  303.     }
  304.  
  305.     /* If this is the first time through and we are at frame #2,
  306.        save our file offset for the next loop through */
  307.  
  308.     if (!(notfirst) && (i==1))
  309.       twopos = Seek (fd, 0, OFFSET_CURRENT);    /* lseek (fd, 0, 1); */
  310.  
  311.     /* Each frame has a header */
  312.  
  313.     read_fheader (fd, &fheader);
  314.  
  315.     for (j=0; j < fheader.fr_chunks; j++)
  316.     {
  317.         /* Each chunk also has a header */
  318.  
  319.         read_chunk (fd, &chunk);
  320.  
  321.         /* Malloc the space to hold whole chunk, unless it
  322.            is a COPY chunk. Malloc/Realloc only if necessary */
  323.  
  324.         if (chunk.ch_type != FLI_COPY) {
  325.         if (!buf)
  326.         {
  327.          if (!(buf = (unsigned char *)malloc(chunk.ch_bytes)))
  328.            Quit (MEM_ERR);
  329.          bufalloc = chunk.ch_bytes;
  330.         }
  331.         else
  332.         {
  333.          if (bufalloc < chunk.ch_bytes)
  334.             {
  335.           if (!(buf = (unsigned char *)realloc(buf, chunk.ch_bytes)))
  336.             Quit (MEM_ERR);
  337.           bufalloc = chunk.ch_bytes;
  338.          }
  339.         }
  340.         }
  341.  
  342.     /* A COPY chunk means 64k of uncompressed image data,
  343.        read it directly into the image */
  344.  
  345.     if (chunk.ch_type == FLI_COPY)
  346.         s = FRead (fd, data, wwidth*wheight, 1);
  347.     else
  348.         s = FRead (fd, buf, chunk.ch_bytes-6, 1);
  349.  
  350.     if (s < 0) {
  351.       Printf ("s: %ld fd: %lx data: 0x%lx chunk.ch_bytes: %ld\n",
  352.                 s, fd, data, chunk.ch_bytes);
  353.       Quit (GET_ERR);
  354.     }
  355.  
  356.     cptr = buf;
  357.  
  358.     switch (chunk.ch_type) {
  359.  
  360.     LONG line;    /* just temporary */
  361.  
  362.     case FLI_COPY:
  363.  
  364. #ifdef DEBUGGING
  365.     printf("CP ww: %ld  wh: %ld\n",wwidth,wheight);
  366. #else
  367.         (*func)(FLI_COPY, i, data, 0,0, 0,0, wwidth,wheight);
  368. #endif
  369.         break;
  370.  
  371.     /* A BLACK chunk */
  372.  
  373.     case FLI_BLACK:
  374.         { /* ULONG *d = (ULONG *)data, anz = wwidth*wheight/4, z;
  375.              for (z=0; z < anz; z++, *d++ = 0);
  376.            */
  377.  
  378.           (*func)(FLI_BLACK, i, data, 0,0, 0,0, wwidth,wheight);
  379.         }
  380.         break;
  381.  
  382.     /* A COLOR chunk: A compressed colormap to be stored or changed */
  383.  
  384.     case FLI_256_COLOR:
  385.  
  386.         npack = get_short(cptr);
  387.  
  388.         for (l=0; l < npack; l++)
  389.         {
  390.             skcount = *(cptr++);     /* # colors not to change */
  391.             skchange = *(cptr++);    /* # of colors to change */
  392.  
  393.             if (!skchange)           /* (0 means all) */
  394.             skchange=MAXCOL;
  395.  
  396.             (*func)(FLI_256_COLOR, i, cptr, skcount,
  397.                 skchange, 0,0, 0,0);
  398.  
  399.             cptr += skchange * 3;
  400.         }
  401.         break;
  402.  
  403.     case FLI_COLOR:
  404.  
  405.         npack = get_short(cptr);
  406.  
  407.         for (l=0; l < npack; l++)
  408.         {
  409.            skcount = *(cptr++);     /* # colors not to change */
  410.            skchange = *(cptr++);    /* # of colors to change */
  411.  
  412.            if (!skchange)           /* (0 means all) */
  413.             skchange=MAXCOL;
  414.  
  415.            /* The colors are stored in the right 6 bits
  416.               of the byte. We then convert it to a short. */
  417.  
  418.            (*func)(FLI_COLOR, i, cptr, skcount, skchange, 0,0, 0,0);
  419.            cptr += skchange * 3;
  420.         }
  421.         break;
  422.  
  423.     /* Line compressed, and bytewise/run-length compressed
  424.        chunks are similar.  BRUN chunks always start at the
  425.        top, while LC chunks can skip lines.  Also, LC chunks
  426.            can skip bytes on each line.  The sign of the
  427.        byte also has opposite meanings for the two! */
  428.  
  429.     case FLI_LC:
  430.  
  431.         curx = 0;
  432.         cury = get_short(cptr);     /* Lines at top to skip */
  433.         ndiff = get_short(cptr);    /* # of lines different */
  434.  
  435.         topy = cury;
  436.         bottomy = cury + ndiff;
  437.  
  438.                leftx = wwidth;
  439.                rightx = 0;
  440.         line = (short)wwidth * (short)cury;
  441.  
  442.         for (k=0; k < ndiff; k++, line += wwidth)    /* Go through each line */
  443.         {
  444.             npack = *(cptr++);       /* # packets this line */
  445.  
  446.             for (l=0; l < npack; l++)
  447.             {
  448.             int i;
  449.             skcount = *(cptr++);    /* # bytes to skip */
  450.  
  451.             if (l == 0 && skcount < leftx)
  452.               leftx = skcount;
  453.  
  454.             curx += skcount;
  455.             dptr = data + line + curx;
  456.  
  457.             /* The number of bytes in this packet to change */
  458.  
  459.             sicount = *(cptr++);
  460.  
  461.             /* Positive, for LC means bytes that change follow,
  462.                for BRUN means one byte to follow, spread it through. */
  463.  
  464.             if (sicount < 128)
  465.             {
  466.                 i = sicount;
  467.                 while (i)
  468.                 {*(dptr++) = *(cptr++); i--;}
  469.             }
  470.             else    /* Negative, the opposite */
  471.             {
  472.                 sicount = 256 - sicount;
  473.                 by = *(cptr++);
  474.                 i = sicount;
  475.                 while (i)
  476.                 {*(dptr++) = by; i--;}
  477.             }
  478.             curx += sicount;
  479.             } /* for (l=0; l < npack; l++) */
  480.  
  481.             if (curx > rightx)
  482.             rightx = curx;
  483.  
  484.             cury++;    /* Next line */
  485.             curx = 0;
  486.         } /* for (k=0; k < ndiff; k++) */
  487.  
  488. #ifdef DEBUGGING
  489.     printf("LC top: %ld  bot: %ld    left: %ld   right: %ld\n",
  490.             topy, bottomy, leftx, rightx);
  491. #else
  492.         (*func)(FLI_LC, i, data,
  493.             leftx,topy, leftx,topy,
  494.             rightx-leftx,bottomy-topy);
  495. #endif
  496.         break;
  497.  
  498.     case FLI_DELTA:
  499.  
  500.         curx = 0;
  501.         cury = 0;
  502.  
  503.         by0 = *(cptr++);
  504.         by1 = *(cptr++);
  505.         ndiff = by0 + 256 * by1;     /* # of lines different */
  506.  
  507.         /* printf(" -- -- ndiff: %ld  frame: %ld\n",ndiff,i); */
  508.  
  509.         topy = 0; bottomy = 0;
  510.  
  511.                leftx = wwidth; rightx = 0;
  512.  
  513.         k=0;
  514.         while (k < ndiff)    /* Go through each line */
  515.         {
  516.             by0 = *(cptr++);
  517.             by1 = *(cptr++);
  518.             npack = by0 + 256 * by1;
  519.  
  520.             line = (short)wwidth * (short)cury;
  521.  
  522.             if (npack >= 32768) npack -= 65536;
  523.  
  524.             /* printf(" -- npack: %ld  cury: %ld\n",npack,cury); */
  525.  
  526.             if (npack < 0)        /* skip lines */
  527.             {
  528.             if (cury == 0)
  529.               topy = -npack;
  530.             cury -= npack;
  531.             continue;
  532.             }
  533.             bottomy = cury+1;
  534.  
  535.             for (l=0; l < npack; l++)
  536.             {
  537.             int i;
  538.  
  539.             skcount = *(cptr++);    /* # bytes to skip */
  540.  
  541.             if (l == 0 && skcount < leftx)
  542.               leftx = skcount;
  543.  
  544.             curx += skcount;
  545.  
  546.             /* printf("pack: %ld  curx: %ld  skip: %ld\n",l,curx,skcount); */
  547.  
  548.             /* The number of words in this packet to change */
  549.  
  550.             sicount = *(cptr++);
  551.  
  552.             /* Positive, for DELTA means sicount words (16 bit)
  553.                that change follow */
  554.  
  555.             i = 2 * sicount;
  556.             dptr = data + line + curx;
  557.  
  558.             if (sicount < 128)
  559.             {
  560.                 while (i)
  561.                 {*(dptr++) = *(cptr++); i--;}
  562.             }
  563.             else    /* Negative, the opposite */
  564.             {
  565.                 sicount = 256 - sicount;
  566.                 by0 = *(cptr++);
  567.                 by1 = *(cptr++);
  568.                 eptr = dptr + 2 * sicount;
  569.  
  570.                 do {
  571.                 *(dptr++) = by0;
  572.                 *(dptr++) = by1;
  573.                 } while (dptr < eptr);
  574.             }
  575.             curx += 2 * sicount;
  576.             }
  577.  
  578.             if (curx > rightx)
  579.             rightx = curx;
  580.  
  581.             cury++;    /* Next line */
  582.             curx = 0;
  583.             k++;
  584.         }
  585.  
  586. #ifdef DEBUGGING
  587.     printf("DL top: %ld  bot: %ld    left: %ld   right: %ld\n",
  588.             topy, bottomy, leftx, rightx);
  589. #else
  590.     (*func)(FLI_DELTA, i, data, leftx,topy, leftx,topy,
  591.         rightx-leftx, bottomy-topy);
  592. #endif
  593.     break;
  594.  
  595.     case FLI_BRUN:
  596.  
  597.         dptr = data;
  598.         eptr = data + wwidth;
  599.  
  600.         for (k=0; k < wheight; k++, eptr += wwidth)    /* Go through each line */
  601.         {
  602.           int i;
  603.           cptr++;    /* skip # packets (buggy PC-shit!) */
  604.  
  605.           while (dptr < eptr) {
  606.  
  607.             /* The number of bytes in this packet to change */
  608.  
  609.             sicount = *(cptr++);
  610.  
  611.             /* Positive, for LC means bytes that change follow,
  612.                for BRUN means one byte to follow, spread it through. */
  613.  
  614.             if (sicount < 128)
  615.             {
  616.              i = sicount;
  617.              by = *cptr++;
  618.              while (i)
  619.             {*(dptr++) = by; i--;}
  620.             }
  621.             else    /* Negative, the opposite */
  622.             {
  623.              sicount = 256 - sicount;
  624.              i = sicount;
  625.              while (i)
  626.             {*(dptr++) = *(cptr++); i--;}
  627.             }
  628.           }
  629.         }
  630. #ifdef DEBUGGING
  631.     printf("BR ww: %ld  wh: %ld\n",wwidth,wheight);
  632. #else
  633.     (*func)(FLI_BRUN, i, data, 0,0, 0,0, wwidth,wheight);
  634. #endif
  635.     break;
  636.  
  637.     } /* switch */
  638.  
  639.      } /* for */
  640.  
  641.     /* Send a FLI_SYNC after each frame to get accurate timing */
  642.  
  643.      (*func)(FLI_SYNC, i, (unsigned char *)0, 0,0, 0,0, 0,0);
  644.  
  645.     } /* for (i=0; i <= header->fhd_frames; i++) */
  646.  
  647.     /* Only free the buffer if we allocated something */
  648.  
  649.     if (buf) {        /* Damned shit was here before (!) */
  650.     free (buf);
  651.     buf = NULL;
  652.     }            
  653. }
  654.